
import { forEachFormOptions, isNumberType } from '@/utils/formMakeUtils.js';
import math from '@/utils/math';
import { statusMap } from '@/filters/status';
// import ElMessage from '@/utils/message';
import { Message } from 'element-ui';
// import { format } from '@/filters/date';
/**
 * 表单提交校验
 * @param {*} formOptions
 * @param {*} isSubmit 是否是提交时验证
 * @returns
 */
export function validateEntireForm(formOptions, isSubmit) {
  const formValidate = formOptions.config.formValidate;
  if (!formValidate || formValidate.length === 0) return null;
  let result = null;
  const errorMsg = [];
  formValidate.forEach(item => {
    if (item.realTime || isSubmit) {
      if (!result) result = getValue(formOptions);
      /*
        前置条件判断
        当前置条件校验不通过 —— 跳过规则校验
        当前置条件校验通过 —— 再对规则进行校验
      */
      const frontAns = validateForm(result, item.frontFilterList || [], item.frontRole || 0);
      if (frontAns) {
        const ans = validateForm(result, item.filterList, item.role);
        if (item.name && !ans) {
          errorMsg.push(item.name);
        } else if (item.accordName && ans) {
          errorMsg.push(item.accordName);
        }
      }
    }
  });
  if (!isSubmit) {
    errorMsg.forEach(i => {
      setTimeout(() => {
        Message.error(i);
      }, 10);
    });
  }

  return errorMsg.length === 0 ? false : errorMsg;
}

/**
 * 组件展示校验
 * @param {*} element 需要判断的组件
 * @param {*} formOptions
 * @returns
 */
export function validateField(element, formOptions, processStatus) {
  let ans = true;
  const isInDetail = !!(processStatus || processStatus === 0);
  const fieldCondition = formOptions.config.fieldCondition;
  if (!fieldCondition || fieldCondition.length === 0) return null;
  let result = null;
  fieldCondition.forEach(condition => {
    // 兼容旧数据
    if (condition.filterList && condition.filterList.length && (!condition.filterListGroup || condition.filterListGroup.length === 0)) {
      condition.filterListGroup = [{
        filterList: condition.filterList,
        role: condition.role || 0
      }];
    }
    const groupIsNotEmpty = condition.filterListGroup && condition.filterListGroup.length;
    if (condition.fieldList && condition.fieldList.length && condition.fieldList.includes(element.key) && groupIsNotEmpty) {
      if (!result) result = getValue(formOptions);
      // 筛选条件组 filterListGroup 为 或 关系，只要有一条符合则停止再验证
      condition.filterListGroup.some(group => {
        const filterList = isInDetail ? group.filterList : group.filterList.filter(j => j.filterField !== 'status');// 非审批详情过来字段为状态的条件
        ans = validateForm(result, filterList, group.role, processStatus);
        return ans;
      });
    }
  });
  if (!result) return null;
  return ans;
}

/**
 * 字段是否有可读权限判断
 * @param {*} element 字段数据
 * @param {*} fieldPermissions 用户不可读字段key集合
 * @returns
 */
export function fieldPermissionJudge(element = {}, fieldPermissions = []) {
  if (!element.options) return true;
  return !fieldPermissions.includes(element.key);
}

/**
 * 校验组件显示条件 或 发起条件
 * @param {*} result 结果值
 * @param {*} filterList 条件列表
 * @param {*} role 规则类型，0: 符合以下全部条件   1:符合以下任一条件
 * @param {*} processStatus 详情流程状态仅详情需要传，0：待提交；1：审批中；2：已完成，3：已作废
 * @returns
 */
function validateForm(result, filterList, role, processStatus) {
  let i = 0;
  const ans = new Array(filterList.length);
  while (i < filterList.length) {
    const filterItem = filterList[i];
    // valueType： value 是选择字段还是值  0:值  1:字段
    let filterElement = result[filterItem.filterField];
    const math = filterItem.math;
    const val2 = filterItem.valueType === 1 && filterItem.value ? result[filterItem.value].value : filterItem.value;
    if (filterItem.filterField === 'status' && (processStatus === 0 || processStatus)) { // 状态作为条件单独判断
      filterElement = {
        type: 'status',
        value: statusMap(processStatus)
      };
    }
    const val2Element = filterItem.valueType === 1 && filterItem.value ? result[filterItem.value] : null;
    const isFit = isEqual(filterElement, val2, math, val2Element);
    if (isFit && role === 1) {
      return true;
    }
    ans[i] = isFit;
    i++;
  }
  return ans.length === 0 || ans.every(i => !!i);
}

/**
 * 递归获取各字段的值
 * @param {*} formOptions
 * @returns
 */
function getValue(formOptions) {
  const result = {};
  forEachFormOptions(formOptions.list, (element, subformKey, parentSubform) => {
    if (element.type !== 'grid' && element.type !== 'title') {
      result[element.key] = JSON.parse(JSON.stringify(element));
      if (isNumberType(element) && element.value) {
        result[element.key].value = element.options.isShowPercentage ? Number(element.value) / 100 : Number(element.value);
      }
    }
    // 计算统计字段数值
    if (element.value && (element.type === 'subform' || (element.type === 'linkForm' && element.options.isStatistics)) && element.options.statistics.length) {
      const statistics = element.options.statistics;
      let unit = '元';
      if (element.type === 'linkForm' && element.options.remoteParams && element.options.remoteParams.isCustom === false) {
        unit = '分';
      }
      const isLinkCustom = element.type === 'linkForm' && element.options.remoteParams && element.options.remoteParams.isCustom;
      statistics.forEach(staticKey => {
        let ans = null;
        element.value.forEach(j => {
          const numVal = isLinkCustom && j.content ? j.content[staticKey] : j[staticKey];
          if (numVal || numVal === 0) {
            const num = unit === '分' ? Number(numVal) / 100 : Number(numVal);
            ans = ans === null ? num : math.add(ans, num);
          }
        });
        result[staticKey] = {
          type: 'statistics',
          value: ans
        };
      });
    }
  }, { notForEachSubform: true });
  return result;
}

/**
 * 以下方法用于比对计算
 */
function isEqual(filterElement = {}, val2, math, val2Element) {
  // string、boolean、number
  if (val2Element && ['upAttachment', 'subform', 'linkForm', 'associatedApproval'].includes(val2Element.type)) {
    val2 = !val2 ? false : !!val2.length;
  }
  // 高级公式字段
  const highLevelFormulaInput = filterElement.type === 'formulaInput' && filterElement.options.modeType;
  if ((highLevelFormulaInput && typeof filterElement.value === 'number') || isNumberType(filterElement) || filterElement.type === 'statistics' || filterElement.type === 'date') {
    const val1Empty = isEmpty(filterElement.value);
    const val2Empty = isEmpty(val2);
    // 空处理，空不能当成是 0
    if (math === '!=') {
      if (val1Empty && val2Empty) return false;
      if (val1Empty || val2Empty) return true;
    } else if (math === '=') {
      if (val1Empty && val2Empty) return true;
      if (val1Empty || val2Empty) return false;
    } else {
      if (val1Empty || val2Empty) return false;
    }
    if (val2Element && ['upAttachment', 'subform', 'linkForm', 'associatedApproval'].includes(val2Element.type)) {
      val2 = NaN;
    }
    if (math === '=') {
      return Number(filterElement.value) === Number(val2);
    } else if (math === '!=') {
      return Number(filterElement.value) !== Number(val2);
    } else if (math === '>') {
      return Number(filterElement.value) > Number(val2);
    } else if (math === '<') {
      return Number(filterElement.value) < Number(val2);
    } else if (math === '>=') {
      return Number(filterElement.value) >= Number(val2);
    } else if (math === '<=') {
      return Number(filterElement.value) <= Number(val2);
    }
    return false;
  } else if (['input', 'textarea', 'richEditor', 'formulaInput', 'link'].includes(filterElement.type)) {
    // 判断空值
    val2 = isEmpty(val2) ? '' : val2;
    if (typeof val2 === 'boolean') {
      val2 = val2 ? '是' : '否';
    }
    // if (val2Element && val2Element.type === 'date' && val2) {
    //   val2 = format(val2, getFormat(val2Element.options.format));
    // }
    if (val2Element && val2Element.type === 'address' && val2) {
      val2 = val2.join('');
    }
    if (val2Element && typeof val2 === 'object') {
      val2 = getDeptOrUserName(val2Element, val2);
      if (Array.isArray(val2)) val2 = val2.join('；');
    } else if (typeof val2 === 'number') {
      val2 = val2.toString();
    }
    if (math === '=') {
      return filterElement.value === val2;
    } else if (math === '!=') {
      return filterElement.value !== val2;
    } else if (math === '包含') {
      if (!filterElement.value && !val2) return true;
      if (!filterElement.value || !val2) return false;
      return filterElement.value.indexOf(val2) >= 0;
    } else if (math === '不包含') {
      if (!filterElement.value && !val2) return false;
      if (!filterElement.value || !val2) return true;
      return filterElement.value.indexOf(val2) < 0;
    }
    return false;
  } else if (['select', 'radio', 'checkbox', 'post', 'department', 'user'].includes(filterElement.type)) {
    let data1 = '';
    let data2 = val2;
    if (filterElement.type === 'department' || filterElement.type === 'user' || filterElement.type === 'post') {
      let labelName = 'name';
      if (filterElement.type === 'user') {
        labelName = 'userName';
      } else {
        labelName = 'name';
      }
      if (!val2Element && (filterElement.type === 'user' || filterElement.type === 'department' || filterElement.type === 'post')) {
        data2 = val2 ? val2.map(i => {
          if (typeof i === 'string') return i;
          return i[labelName];
        }) : [];
      }
      if (Array.isArray(filterElement.value)) {
        data1 = filterElement.value.map(i => i[labelName]);
      } else {
        data1 = filterElement.value ? filterElement.value[labelName] : filterElement.value;
      }
    } else {
      data1 = filterElement.value;
    }
    // 如果是字段
    if (val2Element && typeof val2 === 'object') {
      data2 = getDeptOrUserName(val2Element, data2);
    } else if (typeof data2 === 'boolean') {
      data2 = data2 ? '是' : '否';
    } else if (typeof data2 === 'number') {
      data2 = data2.toString();
    }
    if (data2 && typeof data2 === 'string') data2 = data2.split('；');
    if (math === '=') {
      return arrayEqual(data1, data2);
    } else if (math === '!=') {
      return !arrayEqual(data1, data2);
    } else if (math === '包含') {
      // 只要 filterElement 中包含了 data2 中的一个就算正确
      return isContain(data1, data2);
    } else if (math === '不包含') {
      // filterElement 完全不包含 data2 中的任意一个
      return !isContain(data1, data2);
    }
    return false;
  } else if (filterElement.type === 'switch') {
    const data = filterElement.value === true ? '是' : '否';
    let data2 = val2;
    if (val2Element) data2 = getDeptOrUserName(val2Element, data2);
    if (Array.isArray(data2)) {
      data2 = data2.join('');
    } else if (typeof val2 === 'boolean') {
      data2 = val2 === true ? '是' : '否';
    }
    if (math === '=') {
      return data === data2;
    } else if (math === '!=') {
      return data !== data2;
    }
    return false;
  } else if (['upAttachment', 'subform', 'linkForm', 'associatedApproval'].includes(filterElement.type)) {
    if (typeof val2 === 'boolean') {
      val2 = val2 ? '数据不为空' : '数据为空';
    }
    if (math === '=') {
      if (val2 === '数据为空') {
        return filterElement.value.length === 0;
      } else if (val2 === '数据不为空') {
        return filterElement.value.length > 0;
      } else {
        return true;
      }
    }
    return false;
  } else if (filterElement.type === 'address') {
    const address = Array.isArray(filterElement.value) ? filterElement.value.join('') : filterElement.value;
    let data2 = val2;
    if (Array.isArray(data2)) {
      data2 = data2.join('');
    }
    if (math === '=') {
      return address === data2;
    } else if (math === '!=') {
      return address !== data2;
    }
    return false;
  } else {
    if (math === '=') {
      return filterElement.value === val2;
    } else if (math === '!=') {
      return filterElement.value !== val2;
    }
  }
}

function arrayEqual(val1, val2) {
  if (val2 && !Array.isArray(val2)) val2 = [val2];
  const val1Emprt = isEmpty(val1);
  const val2Emprt = isEmpty(val2);
  if (val1Emprt && val2Emprt) return true;
  if (val1Emprt || val2Emprt) return false;
  if (Array.isArray(val1) && val1.length === val2.length) {
    // 多选
    return val1.every(i => {
      return val2.includes(i);
    });
  } else if (!Array.isArray(val1) && val2.length === 1) {
    // 单选
    return val1 === val2[0];
  }
  return false;
}
function isContain(val1, val2) {
  const val1Empty = isEmpty(val1);
  const val2Empty = isEmpty(val2);
  if (val1Empty && val2Empty) return true; // 如果val1 和 val2 都为空，说明 val1 包含了 空
  if (val1Empty || val2Empty) return false;// 已经排除了同时为空的情况，其他情况下，只要有一方为空就是不匹配
  if (Array.isArray(val1)) {
    return val1.some(i => val2.includes(i));
  } else {
    return val2.some(i => i === val1);
  }
}

function isEmpty(val) {
  if (!val && val !== 0 && val !== false) return true;
  if (Array.isArray(val) && val.length === 0) return true;
  if (typeof val === 'object' && JSON.stringify(val) === '{}') return true;
  return false;
}

function getDeptOrUserName(element, val) {
  if (!element || isEmpty(val) || typeof val !== 'object') return val;
  let labelName = '';
  if (element.type === 'user') labelName = 'userName';
  if (element.type === 'department') labelName = 'name';
  if (element.type === 'post') labelName = 'name';
  let data = '';
  if (Array.isArray(val)) {
    data = val ? val.map(i => labelName ? i[labelName] : i) : [];
  } else if (labelName) {
    data = val[labelName];
  }
  return data;
}

// function getFormat(format) {
//   if (!format) return 'YYYY/MM/DD HH:mm:ss';
//   format = format.replace('yyyy', 'YYYY');
//   format = format.replace('dd', 'DD');
//   return format;
// }
